package others
{
	import flash.utils.ByteArray;
	
	import model.ModelLibrary;
	
	import org.flashIso.engine.base.IsoRoom;
	import org.flashIso.engine.library.objects.LBinaryData;
	import org.flashIso.engine.library.objects.LObject;
	import org.flashIso.engine.library.objects.LImage;
	import org.flashIso.engine.library.objects.LTile;
	import org.flashIso.engine.objects.IsoObject;
	import org.flashIso.engine.objects.IsoImage;
	import org.flashIso.engine.objects.IsoTile;
	public class EditorIsoFactory
	{
		protected static function lBinaryDataToByteArray(lBinaryData:LBinaryData) : ByteArray {
			var obj:Object = new Object();
			obj["id"] = lBinaryData.id;
			obj["data"] = lBinaryData.data;
//			obj["path"] = lBinaryData.path;
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			return data;
		}
		protected static function lBinaryDataFromByteArray(data:ByteArray) : LBinaryData {
			var bData:LBinaryData = new LBinaryData();
			var obj:Object = data.readObject();
			bData.id = obj["id"];
			bData.data = obj["data"];
//			bData.path = obj["path"];
			return bData;
		}
		protected static function lImageToByteArray(lImage:LImage) : ByteArray {
			var obj:Object = new Object();
			obj["id"] = lImage.id;
			obj["data"] = lImage.data;
//			obj["path"] = lImage.path;
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			return data;
		}
		protected static function lImageFromByteArray(data:ByteArray) : LImage {
			var bData:LImage = new LImage();
			var obj:Object = data.readObject();
			bData.id = obj["id"];
			bData.data = obj["data"];
//			bData.path = obj["path"];
			return bData;
		}
		protected static function lObjectToByteArray(lObject:LObject) : ByteArray {
			var obj:Object = new Object();
			obj["deltaX"] = lObject.deltaX;
			obj["deltaY"] = lObject.deltaY;
			obj["deltaZ"] = lObject.deltaZ;
			obj["fillAlpha"] = lObject.fillAlpha;
			obj["fillColor"] = lObject.fillColor;
			obj["id"] = lObject.id;
			if (lObject.image != null){
				obj["imageID"] = lObject.image.id;
			}
			obj["imageAlpha"] = lObject.imageAlpha;
			obj["imageRotation"] = lObject.imageRotation;
			obj["imageScaleX"] = lObject.imageScaleX;
			obj["imageScaleY"] = lObject.imageScaleY;
			obj["imageX"] = lObject.imageX;
			obj["imageY"] = lObject.imageY;
			obj["lineAlpha"] = lObject.lineAlpha;
			obj["lineColor"] = lObject.lineColor;
			obj["lineThickness"] = lObject.lineThickness;
			obj["xSize"] = lObject.xSize;
			obj["ySize"] = lObject.ySize;
			obj["zSize"] = lObject.zSize;
			obj["drawShape"] = lObject.drawShape;
			obj["hitAreaType"] = lObject.hitAreaType;
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			return data;
		}
		protected static function lObjectFromByteArray(data:ByteArray, library:ModelLibrary) : LObject {
			var lObject:LObject = new LObject();
			var obj:Object = data.readObject();
			lObject.deltaX = parseFloat(obj["deltaX"]);
			lObject.deltaY = parseFloat(obj["deltaY"]);
			lObject.deltaZ = parseFloat(obj["deltaZ"]);
			lObject.fillAlpha = parseFloat(obj["fillAlpha"]);
			lObject.fillColor = parseFloat(obj["fillColor"]);
			lObject.id = obj["id"];
			lObject.imageAlpha = parseFloat(obj["imageAlpha"]);
			lObject.imageRotation = parseFloat(obj["imageRotation"]);
			lObject.imageScaleX = parseFloat(obj["imageScaleX"]);
			lObject.imageScaleY = parseFloat(obj["imageScaleY"]);
			lObject.imageX = parseFloat(obj["imageX"]);
			lObject.imageY = parseFloat(obj["imageY"]);
			lObject.lineAlpha = parseFloat(obj["lineAlpha"]);
			lObject.lineColor = parseFloat(obj["lineColor"]);
			lObject.lineThickness = parseFloat(obj["lineThickness"]);
			lObject.xSize = parseFloat(obj["xSize"]);
			lObject.ySize = parseFloat(obj["ySize"]);
			lObject.zSize = parseFloat(obj["zSize"]);
			lObject.drawShape = obj["drawShape"];
			lObject.hitAreaType = obj["hitAreaType"];
			if (library != null && obj["imageID"] != undefined){
				lObject.image = library.getLImageByID(obj["imageID"]);
			}
			return lObject;
		}
		protected static function lTileToByteArray(tile:LTile) : ByteArray {
			var obj:Object = new Object();
			obj["deltaX"] = tile.deltaX;
			obj["deltaY"] = tile.deltaY;
			obj["deltaZ"] = tile.deltaZ;
			obj["fillAlpha"] = tile.fillAlpha;
			obj["fillColor"] = tile.fillColor;
			obj["id"] = tile.id;
			if (tile.image != null){
				obj["imageID"] = tile.image.id;
			}
			obj["imageAlpha"] = tile.imageAlpha;
			obj["imageRotation"] = tile.imageRotation;
			obj["imageScaleX"] = tile.imageScaleX;
			obj["imageScaleY"] = tile.imageScaleY;
			obj["imageX"] = tile.imageX;
			obj["imageY"] = tile.imageY;
			obj["lineAlpha"] = tile.lineAlpha;
			obj["lineColor"] = tile.lineColor;
			obj["lineThickness"] = tile.lineThickness;
			obj["xSize"] = tile.xSize;
			obj["ySize"] = tile.ySize;
			obj["zSize"] = tile.zSize;
			obj["elevationNorth"] = tile.elevationNorth;
			obj["elevationSouth"] = tile.elevationSouth;
			obj["elevationEast"] = tile.elevationEast;
			obj["elevationWest"] = tile.elevationWest;
			obj["drawShape"] = tile.drawShape;
			obj["hitAreaType"] = tile.hitAreaType;
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			return data;
		}
		protected static function lTileFromByteArray(data:ByteArray, library:ModelLibrary) : LTile {
			var tile:LTile = new LTile();
			var obj:Object = data.readObject();
			tile.deltaX = parseFloat(obj["deltaX"]);
			tile.deltaY = parseFloat(obj["deltaY"]);
			tile.deltaZ = parseFloat(obj["deltaZ"]);
			tile.fillAlpha = parseFloat(obj["fillAlpha"]);
			tile.fillColor = parseFloat(obj["fillColor"]);
			tile.id = obj["id"];
			tile.imageAlpha = parseFloat(obj["imageAlpha"]);
			tile.imageRotation = parseFloat(obj["imageRotation"]);
			tile.imageScaleX = parseFloat(obj["imageScaleX"]);
			tile.imageScaleY = parseFloat(obj["imageScaleY"]);
			tile.imageX = parseFloat(obj["imageX"]);
			tile.imageY = parseFloat(obj["imageY"]);
			tile.lineAlpha = parseFloat(obj["lineAlpha"]);
			tile.lineColor = parseFloat(obj["lineColor"]);
			tile.lineThickness = parseFloat(obj["lineThickness"]);
			tile.xSize = parseFloat(obj["xSize"]);
			tile.ySize = parseFloat(obj["ySize"]);
			tile.zSize = parseFloat(obj["zSize"]);
			
			tile.elevationNorth = parseFloat(obj["elevationNorth"]);
			tile.elevationSouth = parseFloat(obj["elevationSouth"]);
			tile.elevationEast = parseFloat(obj["elevationEast"]);
			tile.elevationWest = parseFloat(obj["elevationWest"]);
			tile.drawShape = obj["drawShape"];
			tile.hitAreaType = obj["hitAreaType"];

			if (library != null && obj["imageID"] != undefined){
				tile.image = library.getLImageByID(obj["imageID"]);
			}
			return tile;
		}
		
		public static function libraryToByteArray(library:ModelLibrary) : ByteArray {
			var images:ByteArray = new ByteArray();
			var binaries:ByteArray = new ByteArray();
			var objects:ByteArray = new ByteArray();
			var tiles:ByteArray = new ByteArray();
			var i:uint;
			
			for (i = 0; i < library.imagesDataProvider.length; i++){
				var imageData:ByteArray = lImageToByteArray(library.imagesDataProvider[i] as LImage);
				images.writeObject(imageData);
			}
			for (i = 0; i < library.binaryDataProvider.length; i++){
				var binaryData:ByteArray = lBinaryDataToByteArray(library.binaryDataProvider[i] as LBinaryData);
				binaries.writeObject(binaryData);
			}
			for (i = 0; i < library.objectsDataProvider.length; i++){
				var objectData:ByteArray = lObjectToByteArray(library.objectsDataProvider[i] as LObject);
				objects.writeObject(objectData);
			}
			for (i = 0; i < library.tilesDataProvider.length; i++){
				var tileData:ByteArray = lTileToByteArray(library.tilesDataProvider[i] as LTile);
				tiles.writeObject(tileData);
			}
			var data:ByteArray = new ByteArray();
			
			data.writeObject(images);
			data.writeObject(binaries);
			data.writeObject(objects);
			data.writeObject(tiles);
			return data;
		}
		public static function libraryFromByteArray(data:ByteArray, library:ModelLibrary) : ModelLibrary {
			if (library == null){
				library = new ModelLibrary();
			}
			library.imagesDataProvider.removeAll();
			library.binaryDataProvider.removeAll();
			library.objectsDataProvider.removeAll();
			library.tilesDataProvider.removeAll();
			
			var objData:ByteArray;
			
			var images:ByteArray;
			images = data.readObject();
			while(images.position < images.length - 1){
				library.imagesDataProvider.addItem(lImageFromByteArray(images.readObject()));
			}
			
			var binaries:ByteArray;
			binaries = data.readObject();
			while(binaries.position < binaries.length - 1){
				library.binaryDataProvider.addItem(lBinaryDataFromByteArray(binaries.readObject()));
			}
			
			var objects:ByteArray;
			objects = data.readObject();
			while(objects.position < objects.length - 1){
				library.objectsDataProvider.addItem(lObjectFromByteArray(objects.readObject(), library));
			}
			
			var tiles:ByteArray;
			tiles = data.readObject();
			while(tiles.position < tiles.length - 1){
				library.tilesDataProvider.addItem(lTileFromByteArray(tiles.readObject(), library));
			}
			
			return library;
		}
		
		protected static function isoImageToByteArray(image:IsoImage) : ByteArray {
			var obj:Object = new Object();

			if (image.libraryReference != null){
				obj["id"] = image.libraryReference.id;
			}			
			obj["x"] = image.x;
			obj["y"] = image.y;
			obj["scaleX"] = image.scaleX;
			obj["scaleY"] = image.scaleY;
			obj["rotation"] = image.rotation;
			obj["alpha"] = image.alpha;
			obj["frame"] = image.frame;
			
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			return data;
		}
		protected static function isoImageFromByteArray(data:ByteArray, library:ModelLibrary) : IsoImage {
			var obj:Object = data.readObject();
			var image:IsoImage = new IsoImage();
			if (obj["id"] != undefined){
				image.libraryReference = library.getLImageByID(obj["id"]);
			}
			image.x = parseFloat(obj["x"]);
			image.y = parseFloat(obj["y"]);
			image.scaleX = parseFloat(obj["scaleX"]);
			image.scaleY = parseFloat(obj["scaleY"]);
			image.rotation = parseFloat(obj["rotation"]);
			image.alpha = parseFloat(obj["alpha"]);
			image.frame = obj["frame"];
			
			return image;
		}
		
		protected static function isoObjectToByteArray(isoObject:IsoObject) : ByteArray {
			var obj:Object = new Object();
			obj["x"] = isoObject.position.x;
			obj["y"] = isoObject.position.y;
			obj["z"] = isoObject.position.z;
			obj["rotation"] = isoObject.rotation;
			obj["alpha"] = isoObject.alpha;
			obj["name"] = isoObject.name;
			obj["libraryReferenceID"] = isoObject.libraryReference.id;
			obj["customProperties"] = isoObject.customProperties;
			var imageData:ByteArray = isoImageToByteArray(isoObject.image);

			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			
			data.writeObject(imageData);
			
			return data;
		}
		protected static function isoObjectFromByteArray(data:ByteArray, library:ModelLibrary) : IsoObject {
			var obj:Object = data.readObject();
			var isoObject:IsoObject = new IsoObject();
			isoObject.position.x = parseFloat(obj["x"]);
			isoObject.position.y = parseFloat(obj["y"]);
			isoObject.position.z = parseFloat(obj["z"]);
			isoObject.rotation = parseFloat(obj["rotation"]);
			isoObject.alpha = parseFloat(obj["alpha"]);
			isoObject.libraryReference = library.getLObjectByID(obj["libraryReferenceID"]);
			isoObject.name = obj["name"];
			isoObject.customProperties = obj["customProperties"];
			
			var imageData:ByteArray = data.readObject();
			isoObject.image = isoImageFromByteArray(imageData, library);
			
			return isoObject;
		}
		
		protected static function isoTileToByteArray(tile:IsoTile) : ByteArray {
			var obj:Object = new Object();
			obj["cellX"] = tile.cell.x;
			obj["cellY"] = tile.cell.y;
			obj["alpha"] = tile.alpha;
			obj["rotation"] = tile.rotation;
			obj["libraryReferenceID"] = tile.libraryReference.id;
			obj["customProperties"] = tile.customProperties;
			obj["name"] = tile.name;
			obj["walkable"] = (tile.walkable+"");
			var imageData:ByteArray = isoImageToByteArray(tile.image);
			var data:ByteArray = new ByteArray();
			data.writeObject(obj);
			data.writeObject(imageData);
			return data;
		}
		
		protected static function isoTileFromByteArray(data:ByteArray, library:ModelLibrary) : IsoTile {
			var obj:Object = data.readObject();
			var tile:IsoTile = new IsoTile();
			tile.cell.x = parseFloat(obj["cellX"]);
			tile.cell.y = parseFloat(obj["cellY"]);
			tile.alpha = parseFloat(obj["alpha"]);
			tile.rotation = parseFloat(obj["rotation"]);
			tile.walkable = ((obj["walkable"]+"") == "true");
			tile.customProperties = obj["customProperties"];
			tile.name = obj["name"];
			var imageData:ByteArray = data.readObject();
			tile.image = isoImageFromByteArray(imageData, library);
			tile.libraryReference = library.getLTileByID(obj["libraryReferenceID"]);
			return tile;
		}
		
		public static function isoRoomToByteArray(room:IsoRoom) : ByteArray {
			var i:uint;
			var data:ByteArray = new ByteArray();
			var tiles:ByteArray = new ByteArray();
			var objects:ByteArray = new ByteArray();
			var background:ByteArray;
			var foreground:ByteArray;
			
			var obj:Object = new Object();
			
			background = isoImageToByteArray(room.background);
			foreground = isoImageToByteArray(room.foreground);

			obj["id"] = room.id;
			obj["cellXSize"] = room.map.cellSize.x;
			obj["cellYSize"] = room.map.cellSize.y;
			obj["gridSize"] = room.map.gridSize;
			obj["perspectiveXAngle"] = room.map.perspective.xAngle;
			obj["perspectiveYAngle"] = room.map.perspective.yAngle;
			obj["perspectiveZAngle"] = room.map.perspective.zAngle;
			data.writeObject(obj);
			for (i = 0; i < room.map.numChildren; i++){
				if (room.map.getChildAt(i) is IsoTile){
					var tileData:ByteArray = isoTileToByteArray(room.map.getChildAt(i) as IsoTile);
					tiles.writeObject(tileData);
				}else
				if (room.map.getChildAt(i) is IsoObject){
					//avoid axis
					if ((room.map.getChildAt(i) as IsoObject).libraryReference != null){
						var isoObjectData:ByteArray = isoObjectToByteArray(room.map.getChildAt(i) as IsoObject);
						objects.writeObject(isoObjectData);
					}
				}
			}
			data.writeObject(tiles);
			data.writeObject(objects);
			data.writeObject(background);
			data.writeObject(foreground);
			
			return data;
		}
		public static function isoRoomFromByteArray(data:ByteArray, library:ModelLibrary) : IsoRoom {
			var obj:Object = data.readObject();
			var len:uint;
			var tiles:ByteArray = new ByteArray();
			var objects:ByteArray = new ByteArray();
			var background:ByteArray = new ByteArray();
			var foreground:ByteArray = new ByteArray();
			
			tiles = data.readObject();
			objects = data.readObject();
			background = data.readObject();
			foreground = data.readObject();
				
			var room:IsoRoom = new IsoRoom();
			room.background = isoImageFromByteArray(background, library);
			room.foreground = isoImageFromByteArray(foreground, library);
			
			room.id = obj["id"];
			room.map.cellSize.x = parseFloat(obj["cellXSize"]);
			room.map.cellSize.y = parseFloat(obj["cellYSize"]);
			room.map.gridSize = parseFloat(obj["gridSize"]);

			room.map.perspective.xAngle = parseFloat(obj["perspectiveXAngle"]);
			room.map.perspective.yAngle = parseFloat(obj["perspectiveYAngle"]);
			room.map.perspective.zAngle = parseFloat(obj["perspectiveZAngle"]);

			while (tiles.position < tiles.length - 1){
				var tileData:ByteArray = tiles.readObject();
				var tile:IsoTile = isoTileFromByteArray(tileData, library);
				room.map.addElement(tile);
			}
			while (objects.position < objects.length - 1){
				var objectData:ByteArray = objects.readObject();
				var object:IsoObject = isoObjectFromByteArray(objectData, library);
				room.map.addElement(object);
			}
			return room;
		}
	}
}